using System;
using Oracle.ManagedDataAccess.Client;
using OracleInternal.Common;
using OracleInternal.Network;
using OracleInternal.ServiceObjects;

namespace OracleInternal.TTC
{
	internal class TTCAQNotification : TTCFunction
	{
		internal static short INIT_KPDNRREQ = 1;

		internal static short COMMIT_KPDNRREQ = 2;

		internal static short ROLLBACK_KPDNRREQ = 3;

		internal static short REINIT_KPDNRREQ = 4;

		internal OracleConnectionImpl m_orclConnImpl;

		private string m_client_id;

		internal bool m_bShutDown;

		internal TTCAQNotification(OracleConnectionImpl orclConnImpl)
			: base(orclConnImpl.m_marshallingEngine, 187, 0)
		{
			m_orclConnImpl = orclConnImpl;
		}

		internal override void ReInit(MarshallingEngine marshallingEngine)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)131328, OracleTraceClassName.TTCVersion, OracleTraceFuncName.ReInit);
			}
			try
			{
				base.ReInit(marshallingEngine);
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)268566528, OracleTraceClassName.TTCVersion, OracleTraceFuncName.ReInit, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)131584, OracleTraceClassName.TTCVersion, OracleTraceFuncName.ReInit);
				}
			}
		}

		internal void SendRequest(short registrationOpCode, string clientId)
		{
			m_client_id = clientId;
			WriteFunctionHeader();
			if (!string.IsNullOrEmpty(clientId))
			{
				byte[] array = m_marshallingEngine.m_dbCharSetConv.ConvertStringToBytes(clientId, 0, clientId.Length);
				m_marshallingEngine.MarshalUB2(array.Length);
				m_marshallingEngine.MarshalCLR(array, 0, array.Length);
			}
			else
			{
				m_marshallingEngine.MarshalSWORD(0);
			}
			m_marshallingEngine.MarshalUB1(registrationOpCode);
			m_marshallingEngine.MarshalSWORD(0);
			m_marshallingEngine.m_oraBufWriter.FlushData();
		}

		internal void ReceiveResponse(object state)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)131328, OracleTraceClassName.TTCAQNotification, OracleTraceFuncName.ReceiveResponse, "Background CIC thread started for receiving notifications from Listener ClientId:" + m_client_id);
			}
			bool flag = false;
			try
			{
				m_marshallingEngine.TTCErrorObject.Initialize();
				while (!flag && !m_bShutDown)
				{
					try
					{
						if (ProviderConfig.m_bTraceLevelPrivate)
						{
							Trace.Write(OracleTraceLevel.Private, OracleTraceTag.TTC, OracleTraceClassName.TTCAQNotification, OracleTraceFuncName.ReceiveResponse, "CIC thread waiting to get first notification for Listener ClientId:" + m_client_id);
						}
						byte b = m_marshallingEngine.UnmarshalSB1();
						switch (b)
						{
						case 23:
							ProcessServerSidePiggybackFunction(0);
							break;
						case 13:
							ReceiveONSEvents();
							flag = true;
							break;
						case 4:
							flag = true;
							m_marshallingEngine.TTCErrorObject.ReadErrorMessage();
							if (m_marshallingEngine.TTCErrorObject.ErrorCode == 1403)
							{
								m_marshallingEngine.TTCErrorObject.Initialize();
							}
							else
							{
								OracleConnectionImpl.CheckForAnyErrorFromDB(m_marshallingEngine.TTCErrorObject);
							}
							break;
						case 9:
							if (m_marshallingEngine.HasEOCSCapability)
							{
								m_marshallingEngine.m_endOfCallStatus = m_marshallingEngine.UnmarshalUB4();
							}
							if (m_marshallingEngine.HasFSAPCapability)
							{
								m_marshallingEngine.m_endToEndECIDSequenceNumber = m_marshallingEngine.UnmarshalUB2();
							}
							flag = true;
							break;
						default:
							if (!m_bShutDown)
							{
								throw new Exception($"Unexpected TTC code: {b}");
							}
							break;
						}
					}
					catch (NetworkException ex)
					{
						if (m_bShutDown)
						{
							if (ProviderConfig.m_bTraceLevelPrivate)
							{
								Trace.Write(OracleTraceLevel.Private, OracleTraceTag.TTC, OracleTraceClassName.TTCAQNotification, OracleTraceFuncName.ReceiveResponse, $"Client has Initiated Listener SHUTDOWN...Break Received with error code:{ex.ErrorCode}");
							}
							continue;
						}
						if (ProviderConfig.m_bTraceLevelPrivate)
						{
							string str = "CIC Disconnected, Seems server closed connection ";
							str += $"[CIC got NetworkException {ex.Message} at {DateTime.Now.ToString()}]";
							Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)268566528, OracleTraceClassName.TTCAQNotification, OracleTraceFuncName.ReceiveResponse, str);
						}
						if (ex.ErrorCode != 3111)
						{
							if (ProviderConfig.m_bTraceLevelPrivate)
							{
								Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)268566528, OracleTraceClassName.TTCAQNotification, OracleTraceFuncName.ReceiveResponse, $"Unexpected Exception with error code:{ex.ErrorCode}");
							}
							((ClientInitiatedConnection)state).ReconnectCallback();
							return;
						}
						if (ProviderConfig.m_bTraceLevelPrivate)
						{
							Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)268566528, OracleTraceClassName.TTCAQNotification, OracleTraceFuncName.ReceiveResponse, $"Break Received from server with error code:{ex.ErrorCode}, Will do Reset to get actual error");
						}
						m_marshallingEngine.m_oracleCommunication.Reset();
					}
					catch (Exception ex2)
					{
						if (ProviderConfig.m_bTraceLevelPrivate)
						{
							Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)268566528, OracleTraceClassName.TTCAQNotification, OracleTraceFuncName.ReceiveResponse, $"CIC got Exception {ex2.Message} at {DateTime.Now.ToString()}");
						}
						if (!m_bShutDown)
						{
							if (ProviderConfig.m_bTraceLevelPrivate)
							{
								Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)268566528, OracleTraceClassName.TTCAQNotification, OracleTraceFuncName.ReceiveResponse, "CIC Disconnected, Seems server closed this connection");
							}
							if (m_marshallingEngine.m_oraBufRdr != null)
							{
								m_marshallingEngine.m_oraBufRdr.ClearState();
							}
							if (flag)
							{
								((ClientInitiatedConnection)state).ReconnectCallback();
								return;
							}
							if (ProviderConfig.m_bTraceLevelPrivate)
							{
								Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)268566528, OracleTraceClassName.TTCAQNotification, OracleTraceFuncName.ReceiveResponse, "Unknown Exception, Will do Break/Reset to get actual error");
							}
							m_marshallingEngine.m_oracleCommunication.Break();
							m_marshallingEngine.m_oracleCommunication.Reset();
						}
					}
				}
			}
			catch (Exception)
			{
				((ClientInitiatedConnection)state).ReconnectCallback();
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)131584, OracleTraceClassName.TTCAQNotification, OracleTraceFuncName.ReceiveResponse);
				}
			}
		}

		internal void ReceiveONSEvents()
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)131328, OracleTraceClassName.TTCAQNotification, OracleTraceFuncName.ReceiveONSEvents);
			}
			NotificationHeader notificationHeader = new NotificationHeader(m_orclConnImpl);
			NotificationMessageProperties notificationMessageProperties = new NotificationMessageProperties(m_marshallingEngine);
			NotificationMessagePayload notificationMessagePayload = new NotificationMessagePayload(m_orclConnImpl);
			try
			{
				while (true)
				{
					notificationHeader.Receive();
					if (ProviderConfig.m_bTraceLevelPrivate)
					{
						Trace.Write(OracleTraceLevel.Private, OracleTraceTag.TTC, OracleTraceClassName.TTCAQNotification, OracleTraceFuncName.ReceiveONSEvents, "New Event is Received for CLIENT_ID:" + m_client_id);
					}
					if (notificationHeader.m_messageType != NotificationHeader.STOP_TFN_KPDNRNF)
					{
						notificationMessageProperties.Receive();
						notificationMessagePayload.Receive(notificationHeader.m_regId);
					}
				}
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)131584, OracleTraceClassName.TTCAQNotification, OracleTraceFuncName.ReceiveONSEvents);
				}
			}
		}
	}
}
